package cn.com.twoke.game.client.games.gomoku.controller;

import cn.com.twoke.game.client.GameClientManager;
import cn.com.twoke.game.client.games.framework.ui.ChatMessage;
import cn.com.twoke.game.client.games.gomoku.GomokuGame;
import cn.com.twoke.game.client.games.gomoku.entity.Chess;

import javax.swing.*;
import java.awt.*;

public class RobotController extends AbstractGomokuController {

    private int[][] board = new int[ROW][COL];

    private static final int MAX_DEPTH = 1;

    @Override
    public void drop(int x, int y) {
        this.game.drop(x, y, this.game.getUserDropingChessType());
        if (this.game.checkWin(x, y, this.game.getUserDropingChessType())) {
            JOptionPane.showMessageDialog(this.game.getWindow(), "玩家获胜!");
            this.game.resetGame();
            return;
        }
        this.game.setCanDropChess(false);
        this.game.updateChessLabel();
        new Thread(() -> {
            for (int _y = 0; _y < ROW; _y++) {
                for (int _x = 0; _x < COL; _x++) {
                    board[_y][_x] =this.game.getGrid()[_y][_x].getType().getType();
                }
            }
            aiMove();
            this.game.setCanDropChess(true);
            this.game.updateChessLabel();
        }).start();
    }

    @Override
    public void undo() { // 人机对局悔棋退两步
        // 退机器下的棋子
        this.game.getChessNotes().pop().setType(Chess.Type.NONE);
        // 退用户下的棋子
        this.game.getChessNotes().pop().setType(Chess.Type.NONE);
    }

    @Override
    public void gameOver() {
        // 退出系统
        int i = JOptionPane.showConfirmDialog(this.game.getWindow(),
                "确认要结束游戏？"

        );
        if (i == JOptionPane.OK_OPTION) {
            if (this.game.isNetwork()) {
                GameClientManager.INSTANCE.stopGame(GomokuGame.ID, this.game.getRoomId(), this.game.getPlayerName());
            } else {
                System.exit(0);
            }
        }
    }

    @Override
    public void sendMessage(String content) {
        this.game.acceptMessage(new ChatMessage(content, this.game.getPlayerName(), System.currentTimeMillis()));
    }

    private void aiMove() {
        Point bestMove = findBestMove();
        if (bestMove!= null) {
            this.game.drop(bestMove.x, bestMove.y, this.game.getNotUserDropingChessType()); // 机器下白棋
            if (this.game.checkWin(bestMove.x, bestMove.y, this.game.getNotUserDropingChessType())) {
                JOptionPane.showMessageDialog(this.game.getWindow(), "机器获胜!");
                this.game.resetGame();
            }
        }
    }

    private Point findBestMove() {
        int bestScore = Integer.MIN_VALUE;
        int alpha = Integer.MIN_VALUE;
        int beta = Integer.MAX_VALUE;
        Point bestMove = null;
        for (int x = 0; x < 15; x++) {
            for (int y = 0; y < 15; y++) {
                if (board[y][x] == Chess.NONE) {
                    board[y][x] = this.game.getNotUserDropingChessType().getType(); // 假设机器落子
                    int score = minimax(alpha, beta, 0, false);
                    board[y][x] = Chess.NONE; // 撤销落子
                    if (score > bestScore) {
                        bestScore = score;
                        bestMove = new Point(x, y);
                    }
                }
            }
        }
        return bestMove;
    }

    private int evaluate() {
        int score = 0;
        // 自己的得分
        score += evaluatePlayer(this.game.getNotUserDropingChessType().getType());
        // 对手的得分
        score -= evaluatePlayer(this.game.getUserDropingChessType().getType());
        return score;
    }

    private int evaluatePlayer(int player) {
        int playerScore = 0;
        // 检查横向
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                int[] pattern = new int[5];
                for (int k = 0; k < 5 && j + k < 15; k++) {
                    pattern[k] = board[i][j + k];
                }
                playerScore += scorePattern(pattern, player);
            }
        }
        // 检查纵向
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                int[] pattern = new int[5];
                for (int k = 0; k < 5 && i + k < 15; k++) {
                    pattern[k] = board[i + k][j];
                }
                playerScore += scorePattern(pattern, player);
            }
        }
        // 检查正斜向
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                int[] pattern = new int[5];
                for (int k = 0; k < 5 && i + k < 15 && j + k < 15; k++) {
                    pattern[k] = board[i + k][j + k];
                }
                playerScore += scorePattern(pattern, player);
            }
        }
        // 检查反斜向
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                int[] pattern = new int[5];
                for (int k = 0; k < 5 && i - k >= 0 && j + k < 15; k++) {
                    pattern[k] = board[i - k][j + k];
                }
                playerScore += scorePattern(pattern, player);
            }
        }
        return playerScore;
    }


    private int scorePattern(int[] pattern, int player) {
        int opponent = player == 1? 2 : 1;
        int playerCount = 0;
        int opponentCount = 0;
        int emptyCount = 0;


        for (int p : pattern) {
            if (p == player) playerCount++;
            else if (p == opponent) opponentCount++;
            else emptyCount++;
        }


        if (playerCount == 5) return 100000;
        if (opponentCount == 5) return -100000;


        // 不同棋型的得分
        if (playerCount == 4 && emptyCount == 1) return 10000; // 活四
        if (playerCount == 3 && emptyCount == 2) return 1000; // 活三
        if (playerCount == 2 && emptyCount == 3) return 100; // 活二
        if (playerCount == 1 && emptyCount == 4) return 10; // 活一


        if (opponentCount == 4 && emptyCount == 1) return -10000; // 对手活四
        if (opponentCount == 3 && emptyCount == 2) return -1000; // 对手活三
        if (opponentCount == 2 && emptyCount == 3) return -100; // 对手活二
        if (opponentCount == 1 && emptyCount == 4) return -10; // 对手活一


        return 0;
    }


    private int minimax(int alpha, int beta, int depth, boolean isMaximizingPlayer) {
        if (depth == MAX_DEPTH || isGameOver()) {
            return evaluate();
        }
        if (isMaximizingPlayer) {
            int bestScore = Integer.MIN_VALUE;
            for (int i = 0; i < 15; i++) {
                for (int j = 0; j < 15; j++) {
                    if (board[i][j] == Chess .NONE) {
                        board[i][j] = this.game.getNotUserDropingChessType().getType(); // 机器落子
                        int move = minimax(alpha, beta,depth + 1, false);
                        board[i][j] = Chess.NONE; // 撤销落子
                        if (move > bestScore) {
                            bestScore = move;
                        }
                        alpha = Math.max(alpha, bestScore);
                        if (beta <= alpha) {
                            break;
                        }
                    }
                }
            }
            return bestScore;
        } else {
            int bestScore = Integer.MAX_VALUE;
            for (int i = 0; i < 15; i++) {
                for (int j = 0; j < 15; j++) {
                    if (board[i][j] == Chess.NONE) {
                        board[i][j] = this.game.getUserDropingChessType().getType(); // 玩家落子
                        System.out.println("beta:" + beta);
                        int move = minimax(alpha, beta,depth + 1, true);
                        board[i][j] = Chess.NONE; // 撤销落子
                        if (move < bestScore) {
                            bestScore = move;
                        }
                        beta = Math.min(bestScore, beta);
                        if (beta <= alpha) {
                            break;
                        }
                    }
                }
            }
            return bestScore;
        }




    }

    private boolean isGameOver() {
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                if (board[i][j] == Chess.NONE) return false;
            }
        }
        return true;
    }

}
